package source.view;

import source.*;
import java.awt.*;
import java.io.*;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.LineBorder;

// TODO add operations to switch between the different screens (overviews)

/**
 * MainScreen is just that... the MainScreen that the end user
 * will be able to see.  I'm not too sure if it needs to implement
 * a Controller but we'll figure something out.  I figure that the 
 * MainScreen will be responsible for setting up its components in 
 * it's constructor.  Some sort of player data will be needed as well
 * @author McDonald's Farm
 *
 */
public class MainScreen extends JFrame {
	private static ConsoleViewport 	consoleViewport;
	private AreaViewport 			areaViewport;
	private StructureOverview 		structureOverview;
	private StatusViewport 			statusViewport;
	private UnitOverview 			unitOverview;
	private JScrollPane				scrollPane;
	private Dimension				scrollPaneDimension;
	
	private static HashMap<String, ImageIcon> unitIconLookup;
	
	/**
	 * Initializes all the fields.  Will probably need to be updated when
	 * the PlayerStatus class and Map class are made.
	 */
	public MainScreen(Map map, Controller c){
		super("Main Screen");

		// This is an elegant way to maximize the screen 
		setExtendedState(MAXIMIZED_BOTH);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		// This is a pretty sketchy way of making sure the gridbag work
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		dim.height = dim.height - 80;
		dim.width = dim.width - 30;
		
		// Initialize MainScreen's viewports
		consoleViewport = new ConsoleViewport();
		consoleViewport.setPreferredSize(new Dimension(dim.width * 3/4, dim.height /4));
		areaViewport = new AreaViewport(map);
		statusViewport = new StatusViewport();
		statusViewport.setPreferredSize(new Dimension(dim.width /4, dim.height));
		
		unitOverview = new UnitOverview(c);
		unitOverview.setPreferredSize(new Dimension(dim.width * 3/4, dim.height * 3/4));
		structureOverview = new StructureOverview(c);
		structureOverview.setPreferredSize(new Dimension(dim.width * 3/4, dim.height * 3/4));
		
		// Temporary borders to view what is going on
		consoleViewport.setBorder(new LineBorder(Color.darkGray, 1));
		statusViewport.setBorder(new LineBorder(Color.darkGray, 1));
		
		scrollPaneDimension = new Dimension(dim.width * 3/4, dim.height * 3/4);
		
		Container pane = getContentPane();
		pane.setLayout(new GridBagLayout());
		
		buildLayout(areaViewport);
		
		initUnitIconLookup();
	}
	
	/**
	 * Writes str to the console followed by a carraige return.
	 * @param str
	 */
	public static void writeToConsole(String str, Color c){
		if(consoleViewport != null)
			consoleViewport.writeToConsole(str, c);
		else
			System.out.println(str);
	}
	
	public static void writeToConsole(String str){
		if(consoleViewport != null)
			consoleViewport.writeToConsole(str, Color.BLACK);
		else
			System.out.println(str);
	}
	/**
	 * Switch out the viewport to the areaViewport
	 */
	public void switchToAreaViewport(){
		getContentPane().removeAll();
		buildLayout(areaViewport);
	}
	/**
	 * Switch out the viewport to the structureOverview
	 */
	public void switchToStructureOverview(){
		getContentPane().removeAll();
		structureOverview.updateOverview();
		buildLayout(structureOverview);
	}
	/**
	 * Switch out the viewport to the unitOverview
	 */
	public void switchToUnitOverview(){
		getContentPane().removeAll();
		unitOverview.updateOverview();
		buildLayout(unitOverview);		
	}
	/**
	 * Update the components
	 */
	public void update()
	{
		areaViewport.update();
	}
	/**
	 * Accessor method for unitOverview attribute
	 */
	public UnitOverview getUnitOverview()
	{
		return unitOverview;
	}
	/** 
	 * Accessor method for structureOverview attribute
	 */
	public StructureOverview getStructureOverview()
	{
		return structureOverview;
	}
	/**
	 * Accessor method for areaViewport attribute
	 * @return the current AreaViewport
	 */
	public AreaViewport getAreaViewport()
	{
		return areaViewport;
	}
	/**
	 * Accessor for statusViewport
	 * @return the statusViewport
	 */
	public StatusViewport getStatusViewport(){
		return statusViewport;
	}
	/**
	 * Build the layout for this MainScreen with the specified panel.
	 * @param comp
	 */
	private void buildLayout(JComponent comp){
		// Our good friend GridBagLayout returns and seems to work this time around.
		Container pane = getContentPane();
		
		scrollPane = new JScrollPane(comp);
		scrollPane.setPreferredSize(scrollPaneDimension);
		
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.NONE;
		c.anchor = GridBagConstraints.PAGE_START;
		
		c.gridx = c.gridy = 0;
		c.gridheight = GridBagConstraints.REMAINDER;
		pane.add(statusViewport, c);
		
		c.gridx = 1;
		c.gridheight = 1;
		c.gridwidth = GridBagConstraints.REMAINDER;
		pane.add(scrollPane, c);
		
		c.gridx = 1;
		c.gridy = GridBagConstraints.RELATIVE;
		c.gridwidth = GridBagConstraints.REMAINDER;
		pane.add(consoleViewport,c);
		
		/* This is a very important call.  It forces the window to 
		   make sure the layout is correct. */
		validate();
		repaint();
	}
	/**
	 * Focus the Map to a certain tile.
	 * @param tile
	 */
	public void focusMap(int x, int y){
		//First we have to make sure the map layout is selected
		if(scrollPane != null){
			JViewport viewport = scrollPane.getViewport();
			if(viewport.getView() == areaViewport){
				// We're on the map
				int xPixel = x * areaViewport.getTileSize();
				int yPixel = y * areaViewport.getTileSize();
				int addX = viewport.getViewSize().width / 2;
				int addY = viewport.getViewSize().height / 2;
				int newX = xPixel - addX + areaViewport.getTileSize();
				int newY = yPixel - addY + (2* areaViewport.getTileSize());
				
				Rectangle rect = new Rectangle(viewport.getViewPosition().x, viewport.getViewPosition().y,
						viewport.getSize().width - areaViewport.getTileSize(), viewport.getSize().height - areaViewport.getTileSize());
				
				if(!rect.contains(new Point(xPixel, yPixel))){
					viewport.setViewPosition(new Point(newX, newY));
					scrollPane.setViewport(viewport);
				}
			}
		}
	}
	/**
	 * Get the unitIconLookup table
	 * @return
	 */
	public static HashMap<String, ImageIcon> getUnitIconLookup(){
		return unitIconLookup;
	}
	/**
	 * Initialize a hash map of Strings and ImageIcons for units and their
	 * orientations.
	 *
	 */
	private void initUnitIconLookup(){
		unitIconLookup = new HashMap<String, ImageIcon>();
		String[] orientations = {"N", "S", "E", "W", "NE", "SE", "NW", "SW"};
		for(int player = 0; player < 2; player++){
			for(int i = 0; i < orientations.length; i++){
				try{
					String s = "data" + File.separator + String.valueOf(player) + File.separator + "Colonist"  + orientations[i] + ".bmp";
					unitIconLookup.put(String.valueOf(player) + UnitType.COLONIST + orientations[i], new ImageIcon(ImageIO.read(new File(s))));
					
					s = "data" + File.separator + player + File.separator + "Explorer" + orientations[i] + ".bmp";
					unitIconLookup.put(String.valueOf(player) + UnitType.EXPLORER + orientations[i], new ImageIcon(ImageIO.read(new File(s))));
				}
				catch(IOException e){ System.out.println(e.getMessage()); }
			}
		}
	}
}
